//Shape.h - Class Shape

#ifndef _SHAPE_H_
#define _SHAPE_H_

#include "Point.h"
#include "Screen.h"

using namespace std;

class Shape
{
protected:
	Point m_point;

	//movments data members
	Point m_originalPoint;
	float m_shiftVer, m_shiftHor;	//vertical and horizontal values of the moving rect
	float m_bucketVer, m_bucketHor;	//vertical and horizontal buckets, summarize the shifts value until it >= 1
	float m_originalShiftVer, m_originalShiftHor; //saves the original values of the shifts (before the direction changes)
	int m_counterShiftVerChanges, m_counterShiftHorChanges; //counters for the changes of the the shifts ***NOT IN USE***
	bool m_changedX, m_changedY;
public:
	//constructor
	Shape(const Point& point) : m_point(point), m_shiftVer(0), m_shiftHor(0), m_bucketVer(0), m_bucketHor(0), 
		m_originalShiftVer(m_shiftVer),  m_originalShiftHor(m_shiftHor), m_counterShiftVerChanges(0), m_counterShiftHorChanges(0),
		m_changedX(false), m_changedY(false) {}

	//seters
	void setPoint(int x, int y) { m_point.set(x, y); };
	void setShifts(float shiftVer, float shiftHor);
	void set(Point point, float shiftVer, float shiftHor);
	void addBucketShiftVer() { m_bucketVer += m_shiftVer; };	//add shift to horizontal bucket 
	void addBucketShiftHor() { m_bucketHor += m_shiftHor; };	//add shift to veritacl bucket
	void subBucketShiftVer() { m_bucketVer -= m_shiftVer; };	//sub shift to horizontal bucket
	void subBucketShiftHor() { m_bucketHor -= m_shiftHor; };	//sub shift to veritacl bucket
	void incCounterShiftVerChanges() { ++m_counterShiftVerChanges; };	//increment the horizontal shift changes
	void incCounterShiftHorChanges() { ++m_counterShiftHorChanges; };	//increment the veritacl shift changes
	void resetShiftCounters() { m_counterShiftVerChanges = m_counterShiftHorChanges = 0; }; //zeros the shift counters
	void resetShiftFlags() { m_changedX = m_changedY = false; } ;  
	void resetBuckets() { m_bucketHor = m_bucketVer = 0; } ;  
	void reloadOriginalPoint() { m_point = m_originalPoint; };
	void reloadOriginalShifts();	//reloads the original shift values
	void saveShiftsToOriginal();	//saves the shifts to the original values
	void saveOriginalPoint() { m_originalPoint = m_point; };
	void flagChangeX() { m_changedX = true; }; // Marks a change is to be performed to X Axis
	void flagChangeY() { m_changedY = true; }; // Marks a change is to be performed to Y Axis
	void changeYdirection() { m_shiftVer *= (-1); };
	void changeXdirection() { m_shiftHor *= (-1); };

	//geters
	Point getPoint() const { return m_point; };
	int getXPoint() const { return m_point.getX(); };
	int getYPoint() const { return m_point.getY(); };
	float getShiftVer() const { return m_shiftVer; };
	float getShiftHor() const { return m_shiftHor; };
	float getOriginalShiftVer() const { return m_originalShiftVer; };
	float getOriginalShiftHor() const { return m_originalShiftHor; };
	float getBucketVer() const { return m_bucketVer; };
	float getBucketHor() const { return m_bucketHor; };
	int getCounterShiftVerChanges() const { return m_counterShiftVerChanges; };
	int getCounterShiftHorChanges() const { return m_counterShiftHorChanges; };
	bool getFlagChangeX() { return  m_changedX; };
	bool getFlagChangeY() { return  m_changedY; };

	//virtual functions
	virtual void draw(char ch, bool isFullFill) const = 0; //virtual draw for shape to screen
	virtual void drawToBuffer(char ch, bool isFullFill, bool isSplit, Screen& scr) const = 0; //virtual draw for shape to buffer
	virtual bool isPointInside(const Point& point) const = 0;	//vurtual checks if a shpe contains a point
	virtual bool isInScreenBoarder() const = 0; //virtual chackes if the shape is in the screen boarders
	virtual void handleCollisions(Shape* shape) = 0; //virtual handels collisions between a shape and the other shapes

	bool isShape(const Point& point) const { return (point.getX() == m_point.getX() && point.getY() == m_point.getY()) ? true : false; }; //checks if a shape is defined by a point 
	void move(int incX, int incY) { m_point.move(incX,incY); };
	void execShifts();
	void execShiftsHor();
	void execShiftsVer();
	void fixShapeNegativePoint() { m_point.fixNegativePoint(); };
};

#endif